using System;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using XLua;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Gta.Common;
using Yoozoo.HRP.Runtime;
using Yoozoo.Mars.Got;
using Yoozoo.Mars.Got.SpriteAnim;
using Random = System.Random;


namespace Yoozoo.Gameplay.RTS
{
    public class ParticleSpriteUnitTestCreator
    {
        private const float FRAME_PER_SECOND = 30;
        private const int DURATION_EXTEND = 100;
        public const int MAX_SPRITE_DIRECTION = 9; 
        private const int MAX_SPRITE_ACTION = 6;
        private ParticleSystem ptSystem;
        private ParticleSystem.Particle[] particlePool;
        private List<SpriteVisitor> GOTSpritePool;
        private List<System.Action> completionCallbacks;
        private ParticleSystemRenderer pRenderer;
        private GameObject systemGo;

        private string altasName = null;

        //public Dictionary<int, Dictionary<SPRITE_ACTION_ENUM, AnimInfoData[]>> SpriteDic;
        public Dictionary<int, SpriteAnimData> SpriteDicEx;
        //public SpriteAnimData SpriteAnimData;
        private int particleCount = 0;
        private float offest;

        private SpriteFrameController frameController;
        private SpriteResourceManager resourceManager;

        private Material particlesMaterial = null;
        private float allLifeTime = 0;
        private Vector3 rotation3D;

        private static int visitKey = -1;
        private bool haveUsed = false;

        private bool needFlip = false;

        public void Initialize(Interface_AnimSpriteSupportTemplate interface_direct, GameObject prefab,
            string m_altasName, Material m_material, int initialCount)
        {
            var go = GameObject.Instantiate(prefab);
            go.name = m_altasName + "Creator";
            SpriteDicEx = new Dictionary<int, SpriteAnimData>();
            frameController = new SpriteFrameController(interface_direct);
            ptSystem = go.GetComponent<ParticleSystem>();
            rotation3D = new Vector3(-90,0,0);//interface_direct.GetBillBoardRotation();
            pRenderer = (ParticleSystemRenderer) ptSystem.GetComponent<Renderer>();
            pRenderer.lengthScale = 1f;
            pRenderer.velocityScale = 1f;
            particlesMaterial = m_material;
            altasName = m_altasName;

            needFlip = true;
            particlePool = new ParticleSystem.Particle[initialCount];
            GOTSpritePool = new List<SpriteVisitor>();
            completionCallbacks = new List<System.Action>();
            particleCount = 0;
            pRenderer.renderMode = ParticleSystemRenderMode.Billboard;
            pRenderer.material = m_material;
            var ptSystemMain = ptSystem.main;
            var maxParticles = SpriteParticleSystemManager.INITAL_PARTICLE_NUM;
            ptSystemMain.maxParticles = maxParticles;
            ptSystemMain.simulationSpeed = 20;
            systemGo = go;
            if (particleCount == 0)
            {
                //systemGo.SetActive(false);
                ParticleSystem.TextureSheetAnimationModule sheet = ptSystem.textureSheetAnimation;
                for (int index = sheet.spriteCount - 1; index >= 0; index--)
                {
                    sheet.RemoveSprite(index);
                }
            }
            SetTextureSheetAnimation();
        }


        private float scale;
        private void SetTextureSheetAnimation()
        {
            SpriteAnimationX spritesAnimationX = LoadSpriteAtlas(altasName);
            scale = spritesAnimationX.scale;
            particlesMaterial.mainTexture = spritesAnimationX.texture;

            ParticleSystem.TextureSheetAnimationModule sheet = ptSystem.textureSheetAnimation;
            //？？说明已经拿到了？？
            if (sheet.spriteCount != 0)
            {
                return;
            }

            sheet.frameOverTimeMultiplier = 1;
            sheet.cycleCount = 1;
          
            AnimInfoData[] sprites_cache = null;
            AnimInfoData animInfoData;
            
            
            //SpriteAnimData = new SpriteAnimData {spriteData = new Dictionary<SPRITE_ACTION_ENUM, AnimInfoDataArray>()};
            AnimInfoDataArray tempAnimInfoArr;
            int animIndex = 0;
            int actionNum = spritesAnimationX.actions.Count;
            //序列帧总的生命周期
            allLifeTime = (spritesAnimationX.totalFrameCount) / FRAME_PER_SECOND * DURATION_EXTEND;
            float startTime = 0;
            int directionCount;
            int recIndex;
            for(int actionKey = 0;  actionKey < MAX_SPRITE_ACTION; actionKey++)
            {
                SpriteAnimationAction spAnimationAction;
                if (!spritesAnimationX.actions.TryGetValue(SpriteFrameController.GetAnimationNameByActionEnum((SPRITE_ACTION_ENUM)actionKey), out spAnimationAction))
                {
                    continue;
                }
                animIndex++;
                //这个用于判断一个动作的8个方向是不是结束了。。。
                directionCount = spAnimationAction.directionSpList.Count;
                tempAnimInfoArr = new AnimInfoDataArray();
                sprites_cache = new AnimInfoData[MAX_SPRITE_DIRECTION];
                tempAnimInfoArr.animData = sprites_cache;

               // SPRITE_ACTION_ENUM actionEnum = (SPRITE_ACTION_ENUM)actionKey;
                //SpriteAnimData.spriteData[actionEnum] = tempAnimInfoArr;
                recIndex = 0;
                for(int directionKey = 0 ; directionKey < MAX_SPRITE_DIRECTION; directionKey++)
                //foreach (var directionKey in spAnimationAction.directionSpList.Keys)
                {
                     
                        //这里的方向是按照序列帧给的方向来的
                        // 一个方向的所有序列帧
                        Dictionary<int,SpriteData> spList;
                        if (spAnimationAction.directionSpList.TryGetValue(directionKey, out spList)) // 如果有这个方向的动画
                        {
                            recIndex++;
                            int spLen = spList.Count;
                            Sprite sp;
                            for(int framesNum = 0; framesNum < spLen; framesNum++)// 一个方向的每一帧
                            {
                                sp = spList[framesNum].sprite;
                               // Debug.Log($"Sprite: {spritesAnimationX.assetName} {actionKey} {directionKey} {sp.name}");
                                sheet.AddSprite(sp);
                            }

                            float duration = spLen / FRAME_PER_SECOND * DURATION_EXTEND;
                            //算出在数组中的位置
                            int pos = actionKey * MAX_SPRITE_DIRECTION + directionKey;
                            //startAliveTimePercents[pos] = (startTime + 0.1f / FRAME_PER_SECOND * DURATION_EXTEND) * 100 / allLifeTime;
                            startTime += duration;
                            //endAliveTimePercents[pos] = (startTime - 0.0f / FRAME_PER_SECOND * DURATION_EXTEND ) * 100 / allLifeTime;
                            //Debug.Log($"Sprite 结算时间: {pos} duration: {duration} allLeft: {allLifeTime} startTime:{startAliveTimePercents[pos]} endTime:{endAliveTimePercents[pos]}");
                            
                        }
                }
            }
            haveUsed = true;
        }
        
        
        private SpriteAnimationX LoadSpriteAtlas(string resNames)
        {
            SpriteAnimationX sax = null;
#if UNITY_EDITOR
            string rp = "Assets/ResourcesAssets/FrameAnimation/tex_" + resNames + ".png";
            var allSubAssets = AssetDatabase.LoadAllAssetsAtPath(rp);
            
            ///获取精灵的数量
            int startIndex = 0;
            int mainTextureIndex = 0;
            if (allSubAssets[0] is Texture2D)
            {
                startIndex = 1;
                mainTextureIndex = 0;
            }

           
            Sprite tmpSprite;
            int _fi = 0;

            var firstW = 1f;
            var firstH = 1f;

            var scale = 1f;
            
            sax = new SpriteAnimationX(resNames);
            sax.texture = (allSubAssets[0] as Texture2D);
            //firstW = tmpSprite.textureRect.width;
            //firstH = tmpSprite.textureRect.height;

            Sprite firstSprite = null;
            for (int i = startIndex; i < allSubAssets.Length; i++)
            {
                tmpSprite = allSubAssets[i] as Sprite;
                if (tmpSprite)
                {
                    _fi++;
                    // 创建动画对象

                    if (firstSprite == null)
                    {
                        firstSprite = tmpSprite;
                    }
                    else if (string.Compare(firstSprite.name, tmpSprite.name, StringComparison.Ordinal) > 0)
                    {
                        firstSprite = tmpSprite;
                    }
                    // 序列帧命名协议： 动作-方向-帧数
                    string[] names = tmpSprite.name.Split('-');
                    int dir = 0;
                    int frame = 0;
                    string actionName = "Attack";
                    if (names.Length == 4)
                    {
                        actionName = names[1];
                        int.TryParse(names[1], out dir);
                        dir = dir - 1;
                        int.TryParse(names[2].Split('(')[0], out frame);
                        if (frame != 0) //防止帧数是从0开始命名的
                        {
                            frame = frame - 1;
                        }
                    }
                    else if (names.Length > 1)
                    {
                        actionName = names[0];
                        int.TryParse(names[1], out dir);
                        dir = dir - 1;
                        int.TryParse(names[2].Split('(')[0], out frame);
                        if (frame != 0) //防止帧数是从0开始命名的
                        {
                            frame = frame - 1;
                        }
                    }
                    else
                    {
                        frame = i - 1;
                    }
                    
                    //方向
                    SpriteAnimationAction spriteAnimAction;
                    if (!sax.actions.TryGetValue(actionName, out spriteAnimAction))
                    {
                        spriteAnimAction = new SpriteAnimationAction(actionName);
                        sax.actions.Add(actionName, spriteAnimAction);
                    }

                    //帧
                    Dictionary<int,SpriteData> spriteList;
                    if (!spriteAnimAction.directionSpList.TryGetValue(dir, out spriteList))
                    {
                        spriteList = new Dictionary<int, SpriteData>();
                        spriteAnimAction.directionSpList.Add(dir, spriteList);
                    }
                    
                    if(!spriteList.ContainsKey(frame))
                        spriteList.Add(frame, new SpriteData
                        {
                            sprite = UnityEngine.Object.Instantiate((Sprite) allSubAssets[i]),
                        });
                }
            }

            if (sax!=null)
            {
                sax.totalFrameCount = _fi;
            }

            firstW = firstSprite.textureRect.width;
            firstH = firstSprite.textureRect.height;
            var min = Mathf.Min(firstW, firstH);
            Debug.LogError(firstW + " " + firstH);
            scale = min / 57f;
            Debug.LogError(scale);
            sax.scale = scale;
            Debug.LogError(scale);
#endif
            return sax;
        }

        public void AddSprite(Vector3 position)
        {
            //SpriteVisitor sprite = MemoryPoolMgr.Instance.GetSpriteVisitor();

            var spriteIndex = GOTSpritePool.Count;
            //sprite.spriteIndex = spriteIndex;

            //{
            //sprite.active = true;
            //};
            //sprite.SetSystemNode_v(this, visitKey);
            //data.removes[spriteIndex] = false;
            //UnityEngine.Profiling.Profiler.EndSample();

            ParticleSystem.Particle pt = new ParticleSystem.Particle
            {
                position = position,
                angularVelocity = 0f,
                rotation3D = rotation3D,
                velocity = Vector3.zero,
                startColor = Color.white,
                startLifetime = allLifeTime,
                remainingLifetime = allLifeTime,
                startSize3D = Vector3.one * scale,
            };
            //sprite.particle = pt;
            //particlePool[particleCount] = pt;
            particleCount++;

            //GOTSpritePool.Add(sprite);
#pragma warning disable 618
            ptSystem.Emit(pt);
        }
    }
}